-- ECE 251 Team B Transit Subsystem
-- This class defines the Finite State Machine control
-- March 3, 2007

LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;

ENTITY transmitFSM IS
	PORT
	(
		Clock								: IN	STD_LOGIC; -- Clock signal
		Queue_isEmpty						: IN	STD_LOGIC; -- Indicates that frame pointer queue is empty
															   -- Sit in idle state until not empty
		Queue_Trans							: IN	STD_LOGIC;  -- Transmission signal from FPQ
															    -- Goes high one clock cycle before data
																-- Goes low one clock cycle before end
		Queue_FP							: IN	STD_LOGIC_VECTOR(8 DOWNTO 0); -- Frame Pointer Transmission Data
		Queue_VLAN_Mem						: IN	STD_LOGIC; -- Bit that indicates VLAN membership if set
		Queue_VLAN_Tag						: IN	STD_LOGIC_VECTOR(31 DOWNTO 0); -- VLAN membership tag
		Mem_Interrupt						: IN	STD_LOGIC; -- Interrupt signal from memory indicating incoming data
															   -- High one clock cycle before start of data
		Mem_Data							: IN	STD_LOGIC_VECTOR(15 DOWNTO 0); -- Incoming data from memory in 16-bit blocks
		Mem_TransDone						: IN	STD_LOGIC; -- Single clock cycle signal indicating end of one frame transmission
		
		FSM_GetNext							: OUT	STD_LOGIC; -- Sends signal to FPQ requesting a new data pointer
		FSM_MemSend							: OUT	STD_LOGIC; -- Signal indicating outgoing data to memory
		FSM_MemData							: OUT	STD_LOGIC_VECTOR(8 DOWNTO 0); -- Data going to memory

		FSM_FrameASend						: OUT	STD_LOGIC; -- Signal indicating data going to frame buffer
		FSM_FrameAData_0					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameAData_1					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameAData_2					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameAData_3					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameAComplete					: OUT	STD_LOGIC; -- Signal indicating frame complete
		FB_BufferAFull						: IN	STD_LOGIC; -- Frame buffers are full
		
		FSM_FrameBSend						: OUT	STD_LOGIC; -- Signal indicating data going to frame buffer
		FSM_FrameBData_0					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameBData_1					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameBData_2					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameBData_3					: OUT	STD_LOGIC_VECTOR(3 DOWNTO 0); -- Data going to frame buffer
		FSM_FrameBComplete					: OUT	STD_LOGIC; -- Signal indicating frame complete
		FB_BufferBFull						: IN	STD_LOGIC; -- Frame buffers are full
	
		VLAN_Mem							: BUFFER	STD_LOGIC;
		VLAN_Tag							: BUFFER	STD_LOGIC_VECTOR(31 DOWNTO 0)
	);
END transmitFSM;

ARCHITECTURE Behavior OF transmitFSM IS
	TYPE state_type IS (RESET, fpREQUEST, fpSEND, dataASEND, dataAREQUEST, dataBSEND, dataBREQUEST, transDONE);
	SIGNAL state: state_type;
BEGIN
	PROCESS (Clock)
		VARIABLE D		: STD_LOGIC_VECTOR(15 DOWNTO 0);
		VARIABLE C	  	: STD_LOGIC_VECTOR(31 DOWNTO 0);
		VARIABLE CNT	: INTEGER := 0;
		VARIABLE FL		: INTEGER := 0;
		VARIABLE NewCRC : STD_LOGIC_VECTOR(31 DOWNTO 0);
	BEGIN
		IF Clock'EVENT AND Clock = '1' THEN
			CASE state IS
				WHEN RESET => -- Reset State
					IF ((FB_BufferAFull = '1') AND (FB_BufferBFull = '1')) THEN
						state <= RESET;
					ELSIF Queue_isEmpty = '0' THEN
						state <= fpREQUEST;
						FSM_GetNext <= '1';
					END IF;
				WHEN fpREQUEST => -- State for requesting a frame pointer from the buffer.
					IF Queue_Trans = '1' THEN
						FSM_GetNext <= '0';
						FSM_MemSend <= '1';
						state <= fpSEND;
					END IF;
				WHEN fpSEND => -- Forward the frame pointer as it receives it from the buffer to the shared memory.
					FSM_MemData <= Queue_FP;
					VLAN_Mem <= Queue_VLAN_Mem;
					VLAN_Tag <= Queue_VLAN_Tag;
					IF Queue_Trans = '0' THEN
						FSM_MemSend <= '0';
						IF FB_BufferAFull = '1' THEN
							state <= dataBREQUEST;
						ELSE
							state <= dataAREQUEST;
						END IF;
					END IF;
				WHEN dataAREQUEST => -- Frame pointer forwarding complete, awaiting new frame from memory.
					FSM_FrameAData_0 <= "0000";
					FSM_FrameAData_1 <= "0000";
					FSM_FrameAData_2 <= "0000";
					FSM_FrameAData_3 <= "0000";
					FSM_MemData <= "000000000";
					IF Mem_Interrupt = '1' THEN
						state <= dataASEND;
						FSM_FrameASend <= '1';
					ELSIF Mem_TransDone = '1' THEN
						state <= transDONE;
						FSM_FrameAComplete <= '1';
					END IF;
				WHEN dataASEND => -- Receiving data, forwarding to MII.
					CNT := CNT + 2;
					IF VLAN_Mem = '0' THEN
						FSM_FrameAData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameAData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameAData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameAData_3 <= Mem_Data(15 DOWNTO 12);
					ELSIF FL > 0 THEN
						FL := FL - 2;
						FSM_FrameAData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameAData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameAData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameAData_3 <= Mem_Data(15 DOWNTO 12);
					ELSIF ((FL > -2) AND (CNT > 22)) THEN
						FL := FL - 2;
						FSM_FrameAData_0 <= NewCRC(19 DOWNTO 16);
						FSM_FrameAData_1 <= NewCRC(23 DOWNTO 20);
						FSM_FrameAData_2 <= NewCRC(27 DOWNTO 24);
						FSM_FrameAData_3 <= NewCRC(31 DOWNTO 28);
					ELSIF (FL < -1) THEN
						FSM_FrameAData_0 <= NewCRC(3 DOWNTO 0);
						FSM_FrameAData_1 <= NewCRC(7 DOWNTO 4);
						FSM_FrameAData_2 <= NewCRC(11 DOWNTO 8);
						FSM_FrameAData_3 <= NewCRC(15 DOWNTO 12);					
					ELSIF CNT = 2 THEN
						FSM_FrameAData_0 <= "0000";
						FSM_FrameAData_1 <= "0000";
						FSM_FrameAData_2 <= "0000";
						FSM_FrameAData_3 <= "0000";
					ELSIF CNT = 4 THEN
						FSM_FrameAData_0 <= VLAN_Tag(19 DOWNTO 16);
						FSM_FrameAData_1 <= VLAN_Tag(23 DOWNTO 20);
						FSM_FrameAData_2 <= VLAN_Tag(27 DOWNTO 24);
						FSM_FrameAData_3 <= VLAN_Tag(31 DOWNTO 28);
					ELSIF CNT = 6 THEN
						FSM_FrameAData_0 <= VLAN_Tag(3 DOWNTO 0);
						FSM_FrameAData_1 <= VLAN_Tag(7 DOWNTO 4);
						FSM_FrameAData_2 <= VLAN_Tag(11 DOWNTO 8);
						FSM_FrameAData_3 <= VLAN_Tag(15 DOWNTO 12);
					ELSIF CNT = 14 THEN
						FL := to_integer(unsigned(Mem_Data));
						FSM_FrameAData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameAData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameAData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameAData_3 <= Mem_Data(15 DOWNTO 12);
					ELSE
						FSM_FrameAData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameAData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameAData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameAData_3 <= Mem_Data(15 DOWNTO 12);
					END IF;
					IF Mem_Interrupt = '0' THEN -- When all data recieved/forwarded, return to reset state.
						FSM_FrameASend <= '0';
						state <= dataAREQUEST;
					END IF;
					IF Mem_TransDone = '1' THEN
						state <= transDONE;
						FSM_FrameAComplete <= '1';
					END IF;
					IF FL > 0 THEN
						D := Mem_Data;
						C := NewCRC;
						NewCRC(0) := D(12) xor D(10) xor D(9) xor D(6) xor D(0) xor C(16) xor 
					                 C(22) xor C(25) xor C(26) xor C(28);
					    NewCRC(1) := D(13) xor D(12) xor D(11) xor D(9) xor D(7) xor D(6) xor 
					                 D(1) xor D(0) xor C(16) xor C(17) xor C(22) xor C(23) xor 
					                 C(25) xor C(27) xor C(28) xor C(29);
					    NewCRC(2) := D(14) xor D(13) xor D(9) xor D(8) xor D(7) xor D(6) xor 
					                 D(2) xor D(1) xor D(0) xor C(16) xor C(17) xor C(18) xor 
					                 C(22) xor C(23) xor C(24) xor C(25) xor C(29) xor C(30);
					    NewCRC(3) := D(15) xor D(14) xor D(10) xor D(9) xor D(8) xor D(7) xor 
					                 D(3) xor D(2) xor D(1) xor C(17) xor C(18) xor C(19) xor 
					                 C(23) xor C(24) xor C(25) xor C(26) xor C(30) xor C(31);
					    NewCRC(4) := D(15) xor D(12) xor D(11) xor D(8) xor D(6) xor D(4) xor 
					                 D(3) xor D(2) xor D(0) xor C(16) xor C(18) xor C(19) xor 
					                 C(20) xor C(22) xor C(24) xor C(27) xor C(28) xor C(31);
					    NewCRC(5) := D(13) xor D(10) xor D(7) xor D(6) xor D(5) xor D(4) xor 
					                 D(3) xor D(1) xor D(0) xor C(16) xor C(17) xor C(19) xor 
					                 C(20) xor C(21) xor C(22) xor C(23) xor C(26) xor C(29);
					    NewCRC(6) := D(14) xor D(11) xor D(8) xor D(7) xor D(6) xor D(5) xor 
					                 D(4) xor D(2) xor D(1) xor C(17) xor C(18) xor C(20) xor 
					                 C(21) xor C(22) xor C(23) xor C(24) xor C(27) xor C(30);
					    NewCRC(7) := D(15) xor D(10) xor D(8) xor D(7) xor D(5) xor D(3) xor 
					                 D(2) xor D(0) xor C(16) xor C(18) xor C(19) xor C(21) xor 
					                 C(23) xor C(24) xor C(26) xor C(31);
					    NewCRC(8) := D(12) xor D(11) xor D(10) xor D(8) xor D(4) xor D(3) xor 
					                 D(1) xor D(0) xor C(16) xor C(17) xor C(19) xor C(20) xor 
					                 C(24) xor C(26) xor C(27) xor C(28);
					    NewCRC(9) := D(13) xor D(12) xor D(11) xor D(9) xor D(5) xor D(4) xor 
					                 D(2) xor D(1) xor C(17) xor C(18) xor C(20) xor C(21) xor 
					                 C(25) xor C(27) xor C(28) xor C(29);
					    NewCRC(10) := D(14) xor D(13) xor D(9) xor D(5) xor D(3) xor D(2) xor 
					                  D(0) xor C(16) xor C(18) xor C(19) xor C(21) xor C(25) xor 
					                  C(29) xor C(30);
					    NewCRC(11) := D(15) xor D(14) xor D(12) xor D(9) xor D(4) xor D(3) xor 
					                  D(1) xor D(0) xor C(16) xor C(17) xor C(19) xor C(20) xor 
					                  C(25) xor C(28) xor C(30) xor C(31);
					    NewCRC(12) := D(15) xor D(13) xor D(12) xor D(9) xor D(6) xor D(5) xor 
					                  D(4) xor D(2) xor D(1) xor D(0) xor C(16) xor C(17) xor 
					                  C(18) xor C(20) xor C(21) xor C(22) xor C(25) xor C(28) xor 
					                  C(29) xor C(31);
					    NewCRC(13) := D(14) xor D(13) xor D(10) xor D(7) xor D(6) xor D(5) xor 
					                  D(3) xor D(2) xor D(1) xor C(17) xor C(18) xor C(19) xor 
					                  C(21) xor C(22) xor C(23) xor C(26) xor C(29) xor C(30);
					    NewCRC(14) := D(15) xor D(14) xor D(11) xor D(8) xor D(7) xor D(6) xor 
					                  D(4) xor D(3) xor D(2) xor C(18) xor C(19) xor C(20) xor 
					                  C(22) xor C(23) xor C(24) xor C(27) xor C(30) xor C(31);
					    NewCRC(15) := D(15) xor D(12) xor D(9) xor D(8) xor D(7) xor D(5) xor 
					                  D(4) xor D(3) xor C(19) xor C(20) xor C(21) xor C(23) xor 
					                  C(24) xor C(25) xor C(28) xor C(31);
					    NewCRC(16) := D(13) xor D(12) xor D(8) xor D(5) xor D(4) xor D(0) xor 
					                  C(0) xor C(16) xor C(20) xor C(21) xor C(24) xor C(28) xor 
					                  C(29);
					    NewCRC(17) := D(14) xor D(13) xor D(9) xor D(6) xor D(5) xor D(1) xor 
					                  C(1) xor C(17) xor C(21) xor C(22) xor C(25) xor C(29) xor 
					                  C(30);
					    NewCRC(18) := D(15) xor D(14) xor D(10) xor D(7) xor D(6) xor D(2) xor 
					                  C(2) xor C(18) xor C(22) xor C(23) xor C(26) xor C(30) xor 
					                  C(31);
					    NewCRC(19) := D(15) xor D(11) xor D(8) xor D(7) xor D(3) xor C(3) xor 
					                  C(19) xor C(23) xor C(24) xor C(27) xor C(31);
					    NewCRC(20) := D(12) xor D(9) xor D(8) xor D(4) xor C(4) xor C(20) xor 
					                  C(24) xor C(25) xor C(28);
					    NewCRC(21) := D(13) xor D(10) xor D(9) xor D(5) xor C(5) xor C(21) xor 
					                  C(25) xor C(26) xor C(29);
					    NewCRC(22) := D(14) xor D(12) xor D(11) xor D(9) xor D(0) xor C(6) xor 
					                  C(16) xor C(25) xor C(27) xor C(28) xor C(30);
					    NewCRC(23) := D(15) xor D(13) xor D(9) xor D(6) xor D(1) xor D(0) xor 
					                  C(7) xor C(16) xor C(17) xor C(22) xor C(25) xor C(29) xor 
					                  C(31);
					    NewCRC(24) := D(14) xor D(10) xor D(7) xor D(2) xor D(1) xor C(8) xor 
					                  C(17) xor C(18) xor C(23) xor C(26) xor C(30);
					    NewCRC(25) := D(15) xor D(11) xor D(8) xor D(3) xor D(2) xor C(9) xor 
					                  C(18) xor C(19) xor C(24) xor C(27) xor C(31);
					    NewCRC(26) := D(10) xor D(6) xor D(4) xor D(3) xor D(0) xor C(10) xor 
					                  C(16) xor C(19) xor C(20) xor C(22) xor C(26);
					    NewCRC(27) := D(11) xor D(7) xor D(5) xor D(4) xor D(1) xor C(11) xor 
					                  C(17) xor C(20) xor C(21) xor C(23) xor C(27);
					    NewCRC(28) := D(12) xor D(8) xor D(6) xor D(5) xor D(2) xor C(12) xor 
					                  C(18) xor C(21) xor C(22) xor C(24) xor C(28);
					    NewCRC(29) := D(13) xor D(9) xor D(7) xor D(6) xor D(3) xor C(13) xor 
					                  C(19) xor C(22) xor C(23) xor C(25) xor C(29);
					    NewCRC(30) := D(14) xor D(10) xor D(8) xor D(7) xor D(4) xor C(14) xor 
					                  C(20) xor C(23) xor C(24) xor C(26) xor C(30);
					    NewCRC(31) := D(15) xor D(11) xor D(9) xor D(8) xor D(5) xor C(15) xor 
					                  C(21) xor C(24) xor C(25) xor C(27) xor C(31);
					END IF;
				WHEN dataBREQUEST => -- Frame pointer forwarding complete, awaiting new frame from memory.
					FSM_FrameBData_0 <= "0000";
					FSM_FrameBData_1 <= "0000";
					FSM_FrameBData_2 <= "0000";
					FSM_FrameBData_3 <= "0000";
					FSM_MemData <= "000000000";
					IF Mem_Interrupt = '1' THEN
						state <= dataBSEND;
						FSM_FrameBSend <= '1';
					ELSIF Mem_TransDone = '1' THEN
						state <= transDONE;
						FSM_FrameBComplete <= '1';
					END IF;
				WHEN dataBSEND => -- Receiving data, forwarding to MII.
					CNT := CNT + 2;
					IF VLAN_Mem = '0' THEN
						FSM_FrameBData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameBData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameBData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameBData_3 <= Mem_Data(15 DOWNTO 12);
					ELSIF FL > 0 THEN
						FL := FL - 2;
						FSM_FrameBData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameBData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameBData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameBData_3 <= Mem_Data(15 DOWNTO 12);
					ELSIF ((FL > -2) AND (CNT > 22)) THEN
						FSM_FrameBData_0 <= NewCRC(19 DOWNTO 16);
						FSM_FrameBData_1 <= NewCRC(23 DOWNTO 20);
						FSM_FrameBData_2 <= NewCRC(27 DOWNTO 24);
						FSM_FrameBData_3 <= NewCRC(31 DOWNTO 28);
					ELSIF FL < -1 THEN
						FSM_FrameBData_0 <= NewCRC(3 DOWNTO 0);
						FSM_FrameBData_1 <= NewCRC(7 DOWNTO 4);
						FSM_FrameBData_2 <= NewCRC(11 DOWNTO 8);
						FSM_FrameBData_3 <= NewCRC(15 DOWNTO 12);			
					ELSIF CNT = 2 THEN
						FSM_FrameBData_0 <= "0000";
						FSM_FrameBData_1 <= "0000";
						FSM_FrameBData_2 <= "0000";
						FSM_FrameBData_3 <= "0000";
					ELSIF CNT = 4 THEN
						FSM_FrameBData_0 <= VLAN_Tag(19 DOWNTO 16);
						FSM_FrameBData_1 <= VLAN_Tag(23 DOWNTO 20);
						FSM_FrameBData_2 <= VLAN_Tag(27 DOWNTO 24);
						FSM_FrameBData_3 <= VLAN_Tag(31 DOWNTO 28);
					ELSIF CNT = 6 THEN
						FSM_FrameBData_0 <= VLAN_Tag(3 DOWNTO 0);
						FSM_FrameBData_1 <= VLAN_Tag(7 DOWNTO 4);
						FSM_FrameBData_2 <= VLAN_Tag(11 DOWNTO 8);
						FSM_FrameBData_3 <= VLAN_Tag(15 DOWNTO 12);
					ELSIF CNT = 14 THEN
						FL := to_integer(unsigned(Mem_Data));
						FSM_FrameBData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameBData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameBData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameBData_3 <= Mem_Data(15 DOWNTO 12);
					ELSE
						FSM_FrameBData_0 <= Mem_Data(3 DOWNTO 0);
						FSM_FrameBData_1 <= Mem_Data(7 DOWNTO 4);
						FSM_FrameBData_2 <= Mem_Data(11 DOWNTO 8);
						FSM_FrameBData_3 <= Mem_Data(15 DOWNTO 12);
					END IF;
					IF Mem_Interrupt = '0' THEN -- When all data recieved/forwarded, return to reset state.
						FSM_FrameBSend <= '0';
						state <= dataBREQUEST;
					END IF;
					IF Mem_TransDone = '1' THEN
						state <= transDONE;
						FSM_FrameBComplete <= '1';
					END IF;
					IF FL > 0 THEN
						D := Mem_Data;
						C := NewCRC;
						NewCRC(0) := D(12) xor D(10) xor D(9) xor D(6) xor D(0) xor C(16) xor 
					                 C(22) xor C(25) xor C(26) xor C(28);
					    NewCRC(1) := D(13) xor D(12) xor D(11) xor D(9) xor D(7) xor D(6) xor 
					                 D(1) xor D(0) xor C(16) xor C(17) xor C(22) xor C(23) xor 
					                 C(25) xor C(27) xor C(28) xor C(29);
					    NewCRC(2) := D(14) xor D(13) xor D(9) xor D(8) xor D(7) xor D(6) xor 
					                 D(2) xor D(1) xor D(0) xor C(16) xor C(17) xor C(18) xor 
					                 C(22) xor C(23) xor C(24) xor C(25) xor C(29) xor C(30);
					    NewCRC(3) := D(15) xor D(14) xor D(10) xor D(9) xor D(8) xor D(7) xor 
					                 D(3) xor D(2) xor D(1) xor C(17) xor C(18) xor C(19) xor 
					                 C(23) xor C(24) xor C(25) xor C(26) xor C(30) xor C(31);
					    NewCRC(4) := D(15) xor D(12) xor D(11) xor D(8) xor D(6) xor D(4) xor 
					                 D(3) xor D(2) xor D(0) xor C(16) xor C(18) xor C(19) xor 
					                 C(20) xor C(22) xor C(24) xor C(27) xor C(28) xor C(31);
					    NewCRC(5) := D(13) xor D(10) xor D(7) xor D(6) xor D(5) xor D(4) xor 
					                 D(3) xor D(1) xor D(0) xor C(16) xor C(17) xor C(19) xor 
					                 C(20) xor C(21) xor C(22) xor C(23) xor C(26) xor C(29);
					    NewCRC(6) := D(14) xor D(11) xor D(8) xor D(7) xor D(6) xor D(5) xor 
					                 D(4) xor D(2) xor D(1) xor C(17) xor C(18) xor C(20) xor 
					                 C(21) xor C(22) xor C(23) xor C(24) xor C(27) xor C(30);
					    NewCRC(7) := D(15) xor D(10) xor D(8) xor D(7) xor D(5) xor D(3) xor 
					                 D(2) xor D(0) xor C(16) xor C(18) xor C(19) xor C(21) xor 
					                 C(23) xor C(24) xor C(26) xor C(31);
					    NewCRC(8) := D(12) xor D(11) xor D(10) xor D(8) xor D(4) xor D(3) xor 
					                 D(1) xor D(0) xor C(16) xor C(17) xor C(19) xor C(20) xor 
					                 C(24) xor C(26) xor C(27) xor C(28);
					    NewCRC(9) := D(13) xor D(12) xor D(11) xor D(9) xor D(5) xor D(4) xor 
					                 D(2) xor D(1) xor C(17) xor C(18) xor C(20) xor C(21) xor 
					                 C(25) xor C(27) xor C(28) xor C(29);
					    NewCRC(10) := D(14) xor D(13) xor D(9) xor D(5) xor D(3) xor D(2) xor 
					                  D(0) xor C(16) xor C(18) xor C(19) xor C(21) xor C(25) xor 
					                  C(29) xor C(30);
					    NewCRC(11) := D(15) xor D(14) xor D(12) xor D(9) xor D(4) xor D(3) xor 
					                  D(1) xor D(0) xor C(16) xor C(17) xor C(19) xor C(20) xor 
					                  C(25) xor C(28) xor C(30) xor C(31);
					    NewCRC(12) := D(15) xor D(13) xor D(12) xor D(9) xor D(6) xor D(5) xor 
					                  D(4) xor D(2) xor D(1) xor D(0) xor C(16) xor C(17) xor 
					                  C(18) xor C(20) xor C(21) xor C(22) xor C(25) xor C(28) xor 
					                  C(29) xor C(31);
					    NewCRC(13) := D(14) xor D(13) xor D(10) xor D(7) xor D(6) xor D(5) xor 
					                  D(3) xor D(2) xor D(1) xor C(17) xor C(18) xor C(19) xor 
					                  C(21) xor C(22) xor C(23) xor C(26) xor C(29) xor C(30);
					    NewCRC(14) := D(15) xor D(14) xor D(11) xor D(8) xor D(7) xor D(6) xor 
					                  D(4) xor D(3) xor D(2) xor C(18) xor C(19) xor C(20) xor 
					                  C(22) xor C(23) xor C(24) xor C(27) xor C(30) xor C(31);
					    NewCRC(15) := D(15) xor D(12) xor D(9) xor D(8) xor D(7) xor D(5) xor 
					                  D(4) xor D(3) xor C(19) xor C(20) xor C(21) xor C(23) xor 
					                  C(24) xor C(25) xor C(28) xor C(31);
					    NewCRC(16) := D(13) xor D(12) xor D(8) xor D(5) xor D(4) xor D(0) xor 
					                  C(0) xor C(16) xor C(20) xor C(21) xor C(24) xor C(28) xor 
					                  C(29);
					    NewCRC(17) := D(14) xor D(13) xor D(9) xor D(6) xor D(5) xor D(1) xor 
					                  C(1) xor C(17) xor C(21) xor C(22) xor C(25) xor C(29) xor 
					                  C(30);
					    NewCRC(18) := D(15) xor D(14) xor D(10) xor D(7) xor D(6) xor D(2) xor 
					                  C(2) xor C(18) xor C(22) xor C(23) xor C(26) xor C(30) xor 
					                  C(31);
					    NewCRC(19) := D(15) xor D(11) xor D(8) xor D(7) xor D(3) xor C(3) xor 
					                  C(19) xor C(23) xor C(24) xor C(27) xor C(31);
					    NewCRC(20) := D(12) xor D(9) xor D(8) xor D(4) xor C(4) xor C(20) xor 
					                  C(24) xor C(25) xor C(28);
					    NewCRC(21) := D(13) xor D(10) xor D(9) xor D(5) xor C(5) xor C(21) xor 
					                  C(25) xor C(26) xor C(29);
					    NewCRC(22) := D(14) xor D(12) xor D(11) xor D(9) xor D(0) xor C(6) xor 
					                  C(16) xor C(25) xor C(27) xor C(28) xor C(30);
					    NewCRC(23) := D(15) xor D(13) xor D(9) xor D(6) xor D(1) xor D(0) xor 
					                  C(7) xor C(16) xor C(17) xor C(22) xor C(25) xor C(29) xor 
					                  C(31);
					    NewCRC(24) := D(14) xor D(10) xor D(7) xor D(2) xor D(1) xor C(8) xor 
					                  C(17) xor C(18) xor C(23) xor C(26) xor C(30);
					    NewCRC(25) := D(15) xor D(11) xor D(8) xor D(3) xor D(2) xor C(9) xor 
					                  C(18) xor C(19) xor C(24) xor C(27) xor C(31);
					    NewCRC(26) := D(10) xor D(6) xor D(4) xor D(3) xor D(0) xor C(10) xor 
					                  C(16) xor C(19) xor C(20) xor C(22) xor C(26);
					    NewCRC(27) := D(11) xor D(7) xor D(5) xor D(4) xor D(1) xor C(11) xor 
					                  C(17) xor C(20) xor C(21) xor C(23) xor C(27);
					    NewCRC(28) := D(12) xor D(8) xor D(6) xor D(5) xor D(2) xor C(12) xor 
					                  C(18) xor C(21) xor C(22) xor C(24) xor C(28);
					    NewCRC(29) := D(13) xor D(9) xor D(7) xor D(6) xor D(3) xor C(13) xor 
					                  C(19) xor C(22) xor C(23) xor C(25) xor C(29);
					    NewCRC(30) := D(14) xor D(10) xor D(8) xor D(7) xor D(4) xor C(14) xor 
					                  C(20) xor C(23) xor C(24) xor C(26) xor C(30);
					    NewCRC(31) := D(15) xor D(11) xor D(9) xor D(8) xor D(5) xor C(15) xor 
					                  C(21) xor C(24) xor C(25) xor C(27) xor C(31);
					END IF;
				WHEN transDONE => -- Finished transmission
					FSM_FrameAData_0 <= "0000";
					FSM_FrameAData_1 <= "0000";
					FSM_FrameAData_2 <= "0000";
					FSM_FrameAData_3 <= "0000";
					FSM_FrameAComplete <= '0';
					FSM_FrameBData_0 <= "0000";
					FSM_FrameBData_1 <= "0000";
					FSM_FrameBData_2 <= "0000";
					FSM_FrameBData_3 <= "0000";
					FSM_FrameBComplete <= '0';
					CNT := 0;
					FL := 0;
					C := "00000000000000000000000000000000";
					NewCRC := "00000000000000000000000000000000";
					state <= RESET;
			END CASE;
		END IF;
	END PROCESS;

END Behavior;
